package com.blog.web.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.blog.common.core.exception.ServiceException;
import com.blog.common.core.utils.HTMLUtils;
import com.blog.common.core.utils.PageUtils;
import com.blog.common.core.utils.ip.IpUtils;
import com.blog.common.core.web.page.TableDataInfo;
import com.blog.common.redis.service.RedisService;
import com.blog.common.domain.entity.Talk;
import com.blog.common.domain.vo.CommentCountVo;
import com.blog.common.domain.vo.TalkVo;
import com.blog.common.mapper.dao.CommentMapper;
import com.blog.common.mapper.dao.TalkMapper;
import com.blog.web.service.TalkService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import static com.blog.common.core.constant.CacheConstants.*;
import static com.blog.common.domain.enums.ArticleEnums.PUBLIC;

/**
 * <p>
 * 说说 服务实现类
 * </p>
 *
 * @author Valerie
 * @since 2023-02-18
 */
@Service
@Slf4j
public class TalkServiceImpl extends ServiceImpl<TalkMapper, Talk> implements TalkService {

    @Resource
    private TalkMapper talkMapper;
    @Resource
    private CommentMapper commentMapper;
    @Resource
    private RedisService redisService;

    @Resource
    private HttpServletRequest request;

    @Override
    public List<String> listHomeTalks() {
        // 查询最新10条说说
        return talkMapper.selectList(new LambdaQueryWrapper<Talk>()
                        .eq(Talk::getStatus, PUBLIC.getStatus())
                        .orderByDesc(Talk::getIsTop)
                        .orderByDesc(Talk::getId)
                        .last("limit 10"))
                .stream()
                .map(item -> item.getContent().length() > 200 ? HTMLUtils.deleteTag(item.getContent().substring(0, 200))
                        : HTMLUtils.deleteTag(item.getContent()))
                .collect(Collectors.toList());
    }

    @Override
    public TableDataInfo<TalkVo> listTalks() {
        // 查询说说总量
        Long count = talkMapper.selectCount((new LambdaQueryWrapper<Talk>()
                .eq(Talk::getStatus, PUBLIC.getStatus())));

        if (count == 0) {
            return new TableDataInfo<>();
        }
        // 分页查询说说
        log.warn(PageUtils.getPageNum().toString());
        Page<TalkVo> talkVoPage = talkMapper.listTalks(PageUtils.getPage());
        List<TalkVo> talkVoList = talkVoPage.getRecords();
        // 查询说说评论量
        List<Long> talkIdList = talkVoList.stream()
                .map(TalkVo::getId)
                .collect(Collectors.toList());
        Map<Long, Long> commentCountMap = commentMapper.listCommentCountByTopicIds(talkIdList)
                .stream()
                .collect(Collectors.toMap(CommentCountVo::getId, CommentCountVo::getCommentCount));
        // 查询说说点赞量
        Map<Object, Object> likeCountMap = redisService.hGetAll(TALK_LIKE_COUNT);
        talkVoList = talkVoList.stream().peek(item -> {
            item.setLikeCount((Long) Optional.ofNullable(likeCountMap.get(item.getId().toString())).orElse(0L));
            item.setCommentCount(Optional.ofNullable(commentCountMap.get(item.getId())).orElse(0L));
            // 转换图片格式
            if (Objects.nonNull(item.getImages())) {
                item.setImgList(JSON.parseObject(item.getImages(), new TypeReference<>() {
                }));
            }
        }).collect(Collectors.toList());
        return new TableDataInfo<>(talkVoList, talkVoPage.getTotal());
    }

    @Override
    public TalkVo getTalkById(Serializable talkId) {
        // 查询说说信息
        TalkVo talkVo = talkMapper.getTalkById((Integer) talkId);
        if (Objects.isNull(talkVo)) {
            log.warn("说说不存在");
            throw new ServiceException("说说不存在");
        }
        // 查询说说点赞量
        talkVo.setLikeCount((Long) redisService.hGet(TALK_LIKE_COUNT, talkId.toString()));
        // 转换图片格式
        if (Objects.nonNull(talkVo.getImages())) {
            talkVo.setImgList(JSON.parseObject(talkVo.getImages(), new TypeReference<>() {
            }));
        }
        return talkVo;
    }

    @Override
    public void saveTalkLike(Serializable talkId) {
        // 判断是否点赞
        String talkLikeKey = TALK_USER_LIKE + IpUtils.getIpAddr(request);
        if (redisService.sIsMember(talkLikeKey, talkId)) {
            // 点过赞则删除说说id
            redisService.sRemove(talkLikeKey, talkId);
            // 说说点赞量-1
            redisService.hDecr(TALK_LIKE_COUNT, talkId.toString(), 1L);
        } else {
            // 未点赞则增加说说id
            redisService.sAdd(talkLikeKey, talkId);
            // 说说点赞量+1
            redisService.hIncr(TALK_LIKE_COUNT, talkId.toString(), 1L);
        }
    }

}
